#include "trackeditinteraction.h"

namespace au::trackedit {
TrackeditInteraction::TrackeditInteraction(std::unique_ptr<ITrackeditInteraction> interaction)
    : m_interaction(std::move(interaction))
{
}

muse::secs_t TrackeditInteraction::clipStartTime(const trackedit::ClipKey& clipKey) const
{
    return m_interaction->clipStartTime(clipKey);
}

muse::secs_t TrackeditInteraction::clipEndTime(const ClipKey& clipKey) const
{
    return m_interaction->clipEndTime(clipKey);
}

bool TrackeditInteraction::changeClipStartTime(const trackedit::ClipKey& clipKey, secs_t newStartTime, bool completed)
{
    return withPlaybackStop(&ITrackeditInteraction::changeClipStartTime, clipKey, newStartTime, completed);
}

muse::async::Channel<trackedit::ClipKey, secs_t /*newStartTime*/, bool /*completed*/> TrackeditInteraction::clipStartTimeChanged() const
{
    return m_interaction->clipStartTimeChanged();
}

bool TrackeditInteraction::trimTracksData(const std::vector<trackedit::TrackId>& tracksIds, secs_t begin, secs_t end)
{
    return withPlaybackStop(&ITrackeditInteraction::trimTracksData, tracksIds, begin, end);
}

bool TrackeditInteraction::silenceTracksData(const std::vector<trackedit::TrackId>& tracksIds, secs_t begin, secs_t end)
{
    return withPlaybackStop(&ITrackeditInteraction::silenceTracksData, tracksIds, begin, end);
}

bool TrackeditInteraction::changeTrackTitle(const trackedit::TrackId trackId, const muse::String& title)
{
    return m_interaction->changeTrackTitle(trackId, title);
}

bool TrackeditInteraction::changeClipTitle(const trackedit::ClipKey& clipKey, const muse::String& newTitle)
{
    return m_interaction->changeClipTitle(clipKey, newTitle);
}

bool TrackeditInteraction::changeClipPitch(const ClipKey& clipKey, int pitch)
{
    return m_interaction->changeClipPitch(clipKey, pitch);
}

bool TrackeditInteraction::resetClipPitch(const ClipKey& clipKey)
{
    return m_interaction->resetClipPitch(clipKey);
}

bool TrackeditInteraction::changeClipSpeed(const ClipKey& clipKey, double speed)
{
    return withPlaybackStop(&ITrackeditInteraction::changeClipSpeed, clipKey, speed);
}

bool TrackeditInteraction::resetClipSpeed(const ClipKey& clipKey)
{
    return withPlaybackStop(&ITrackeditInteraction::resetClipSpeed, clipKey);
}

bool TrackeditInteraction::changeClipColor(const ClipKey& clipKey, const std::string& color)
{
    return m_interaction->changeClipColor(clipKey, color);
}

bool TrackeditInteraction::changeTracksColor(const TrackIdList& tracksIds, const std::string& color)
{
    return m_interaction->changeTracksColor(tracksIds, color);
}

bool TrackeditInteraction::changeTrackRulerType(const trackedit::TrackId& trackId, trackedit::TrackRulerType rulerType)
{
    return m_interaction->changeTrackRulerType(trackId, rulerType);
}

bool TrackeditInteraction::changeAudioTrackViewType(const trackedit::TrackId& trackId, trackedit::TrackViewType viewType)
{
    return m_interaction->changeAudioTrackViewType(trackId, viewType);
}

bool TrackeditInteraction::changeClipOptimizeForVoice(const ClipKey& clipKey, bool optimize)
{
    return withPlaybackStop(&ITrackeditInteraction::changeClipOptimizeForVoice, clipKey, optimize);
}

bool TrackeditInteraction::renderClipPitchAndSpeed(const ClipKey& clipKey)
{
    return withPlaybackStop(&ITrackeditInteraction::renderClipPitchAndSpeed, clipKey);
}

void TrackeditInteraction::clearClipboard()
{
    return m_interaction->clearClipboard();
}

muse::Ret TrackeditInteraction::pasteFromClipboard(secs_t begin, bool moveClips, bool moveAllTracks)
{
    return withPlaybackStop(&ITrackeditInteraction::pasteFromClipboard, begin, moveClips, moveAllTracks);
}

bool TrackeditInteraction::cutClipIntoClipboard(const ClipKey& clipKey)
{
    return withPlaybackStop(&ITrackeditInteraction::cutClipIntoClipboard, clipKey);
}

bool TrackeditInteraction::cutItemDataIntoClipboard(const TrackIdList& tracksIds, secs_t begin, secs_t end, bool moveClips)
{
    return withPlaybackStop(&ITrackeditInteraction::cutItemDataIntoClipboard, tracksIds, begin, end, moveClips);
}

bool TrackeditInteraction::copyClipIntoClipboard(const trackedit::ClipKey& clipKey)
{
    return m_interaction->copyClipIntoClipboard(clipKey);
}

bool TrackeditInteraction::copyNonContinuousTrackDataIntoClipboard(const TrackId trackId, const ClipKeyList& clipKeys, secs_t offset)
{
    return m_interaction->copyNonContinuousTrackDataIntoClipboard(trackId, clipKeys, offset);
}

bool TrackeditInteraction::copyContinuousTrackDataIntoClipboard(const TrackId trackId, secs_t begin, secs_t end)
{
    return m_interaction->copyContinuousTrackDataIntoClipboard(trackId, begin, end);
}

bool TrackeditInteraction::removeClip(const trackedit::ClipKey& clipKey)
{
    return withPlaybackStop(&ITrackeditInteraction::removeClip, clipKey);
}

bool TrackeditInteraction::removeClips(const ClipKeyList& clipKeyList, bool moveClips)
{
    return withPlaybackStop(&ITrackeditInteraction::removeClips, clipKeyList, moveClips);
}

bool TrackeditInteraction::removeTracksData(const TrackIdList& tracksIds, secs_t begin, secs_t end, bool moveClips)
{
    return withPlaybackStop(&ITrackeditInteraction::removeTracksData, tracksIds, begin, end, moveClips);
}

bool TrackeditInteraction::moveClips(secs_t timePositionOffset, int trackPositionOffset, bool completed, bool& clipsMovedToOtherTrack)
{
    return withPlaybackStop(&ITrackeditInteraction::moveClips,
                            timePositionOffset,
                            trackPositionOffset,
                            completed,
                            clipsMovedToOtherTrack);
}

void TrackeditInteraction::cancelItemDragEdit()
{
    m_interaction->cancelItemDragEdit();
}

bool TrackeditInteraction::splitTracksAt(const TrackIdList& tracksIds, std::vector<secs_t> pivots)
{
    return withPlaybackStop(&ITrackeditInteraction::splitTracksAt, tracksIds, pivots);
}

bool TrackeditInteraction::splitClipsAtSilences(const ClipKeyList& clipKeyList)
{
    return withPlaybackStop(&ITrackeditInteraction::splitClipsAtSilences, clipKeyList);
}

bool TrackeditInteraction::splitRangeSelectionAtSilences(const TrackIdList& tracksIds, secs_t begin, secs_t end)
{
    return withPlaybackStop(&ITrackeditInteraction::splitRangeSelectionAtSilences, tracksIds, begin, end);
}

bool TrackeditInteraction::splitRangeSelectionIntoNewTracks(const TrackIdList& tracksIds, secs_t begin, secs_t end)
{
    return withPlaybackStop(&ITrackeditInteraction::splitRangeSelectionIntoNewTracks, tracksIds, begin, end);
}

bool TrackeditInteraction::splitClipsIntoNewTracks(const ClipKeyList& clipKeyList)
{
    return withPlaybackStop(&ITrackeditInteraction::splitClipsIntoNewTracks, clipKeyList);
}

bool TrackeditInteraction::mergeSelectedOnTracks(const TrackIdList& tracksIds, secs_t begin, secs_t end)
{
    return withPlaybackStop(&ITrackeditInteraction::mergeSelectedOnTracks, tracksIds, begin, end);
}

bool TrackeditInteraction::duplicateSelectedOnTracks(const TrackIdList& tracksIds, secs_t begin, secs_t end)
{
    return withPlaybackStop(&ITrackeditInteraction::duplicateSelectedOnTracks, tracksIds, begin, end);
}

bool TrackeditInteraction::duplicateClip(const ClipKey& clipKey)
{
    return withPlaybackStop(&ITrackeditInteraction::duplicateClip, clipKey);
}

bool TrackeditInteraction::duplicateClips(const ClipKeyList& clipKeyList)
{
    return withPlaybackStop(&ITrackeditInteraction::duplicateClips, clipKeyList);
}

bool TrackeditInteraction::clipSplitCut(const ClipKey& clipKey)
{
    return withPlaybackStop(&ITrackeditInteraction::clipSplitCut, clipKey);
}

bool TrackeditInteraction::clipSplitDelete(const ClipKey& clipKey)
{
    return withPlaybackStop(&ITrackeditInteraction::clipSplitDelete, clipKey);
}

bool TrackeditInteraction::splitCutSelectedOnTracks(const TrackIdList tracksIds, secs_t begin, secs_t end)
{
    return withPlaybackStop(&ITrackeditInteraction::splitCutSelectedOnTracks, tracksIds, begin, end);
}

bool TrackeditInteraction::splitDeleteSelectedOnTracks(const TrackIdList tracksIds, secs_t begin, secs_t end)
{
    return withPlaybackStop(&ITrackeditInteraction::splitDeleteSelectedOnTracks, tracksIds, begin, end);
}

bool TrackeditInteraction::trimClipLeft(const ClipKey& clipKey, secs_t deltaSec, secs_t minClipDuration, bool completed, UndoPushType type)
{
    return withPlaybackStop(&ITrackeditInteraction::trimClipLeft, clipKey, deltaSec, minClipDuration, completed, type);
}

bool TrackeditInteraction::trimClipRight(const ClipKey& clipKey, secs_t deltaSec, secs_t minClipDuration, bool completed, UndoPushType type)
{
    return withPlaybackStop(&ITrackeditInteraction::trimClipRight, clipKey, deltaSec, minClipDuration, completed, type);
}

bool TrackeditInteraction::stretchClipLeft(const ClipKey& clipKey,
                                           secs_t deltaSec,
                                           secs_t minClipDuration,
                                           bool completed,
                                           UndoPushType type)
{
    return withPlaybackStop(&ITrackeditInteraction::stretchClipLeft, clipKey, deltaSec, minClipDuration, completed, type);
}

bool TrackeditInteraction::stretchClipRight(const ClipKey& clipKey,
                                            secs_t deltaSec,
                                            secs_t minClipDuration,
                                            bool completed,
                                            UndoPushType type)
{
    return withPlaybackStop(&ITrackeditInteraction::stretchClipRight,
                            clipKey,
                            deltaSec,
                            minClipDuration,
                            completed,
                            type);
}

muse::secs_t TrackeditInteraction::clipDuration(const trackedit::ClipKey& clipKey) const
{
    return m_interaction->clipDuration(clipKey);
}

std::optional<secs_t> TrackeditInteraction::getLeftmostClipStartTime(const ClipKeyList& clipKeys) const
{
    return m_interaction->getLeftmostClipStartTime(clipKeys);
}

std::optional<secs_t> TrackeditInteraction::getRightmostClipEndTime(const ClipKeyList& clipKeys) const
{
    return m_interaction->getRightmostClipEndTime(clipKeys);
}

double TrackeditInteraction::nearestZeroCrossing(double time) const
{
    return m_interaction->nearestZeroCrossing(time);
}

muse::Ret TrackeditInteraction::makeRoomForClip(const ClipKey& clipKey)
{
    return m_interaction->makeRoomForClip(clipKey);
}

bool TrackeditInteraction::newMonoTrack()
{
    return withPlaybackStop(&ITrackeditInteraction::newMonoTrack);
}

bool TrackeditInteraction::newStereoTrack()
{
    return withPlaybackStop(&ITrackeditInteraction::newStereoTrack);
}

bool TrackeditInteraction::newLabelTrack()
{
    return withPlaybackStop(&ITrackeditInteraction::newLabelTrack);
}

bool TrackeditInteraction::deleteTracks(const TrackIdList& trackIds)
{
    return withPlaybackStop(&ITrackeditInteraction::deleteTracks, trackIds);
}

bool TrackeditInteraction::duplicateTracks(const TrackIdList& trackIds)
{
    return withPlaybackStop(&ITrackeditInteraction::duplicateTracks, trackIds);
}

void TrackeditInteraction::moveTracks(const TrackIdList& trackIds, const TrackMoveDirection direction)
{
    return m_interaction->moveTracks(trackIds, direction);
}

void TrackeditInteraction::moveTracksTo(const TrackIdList& trackIds, int to)
{
    return m_interaction->moveTracksTo(trackIds, to);
}

ClipKeyList TrackeditInteraction::clipsOnTrack(const TrackId trackId)
{
    return m_interaction->clipsOnTrack(trackId);
}

bool TrackeditInteraction::undo()
{
    return withPlaybackStop(&ITrackeditInteraction::undo);
}

bool TrackeditInteraction::canUndo()
{
    return m_interaction->canUndo();
}

bool TrackeditInteraction::redo()
{
    return withPlaybackStop(&ITrackeditInteraction::redo);
}

bool TrackeditInteraction::canRedo()
{
    return m_interaction->canRedo();
}

bool TrackeditInteraction::undoRedoToIndex(size_t index)
{
    return m_interaction->undoRedoToIndex(index);
}

muse::async::Notification TrackeditInteraction::cancelDragEditRequested() const
{
    return m_interaction->cancelDragEditRequested();
}

void TrackeditInteraction::notifyAboutCancelDragEdit()
{
    m_interaction->notifyAboutCancelDragEdit();
}

bool TrackeditInteraction::insertSilence(const TrackIdList& trackIds, secs_t begin, secs_t end, secs_t duration)
{
    return withPlaybackStop(&ITrackeditInteraction::insertSilence, trackIds, begin, end, duration);
}

bool TrackeditInteraction::toggleStretchToMatchProjectTempo(const ClipKey& clipKey)
{
    return withPlaybackStop(&ITrackeditInteraction::toggleStretchToMatchProjectTempo, clipKey);
}

int64_t TrackeditInteraction::clipGroupId(const ClipKey& clipKey) const
{
    return m_interaction->clipGroupId(clipKey);
}

void TrackeditInteraction::setClipGroupId(const ClipKey& clipKey, int64_t id)
{
    return m_interaction->setClipGroupId(clipKey, id);
}

void TrackeditInteraction::groupClips(const ClipKeyList& clipKeyList)
{
    return m_interaction->groupClips(clipKeyList);
}

void TrackeditInteraction::ungroupClips(const ClipKeyList& clipKeyList)
{
    return m_interaction->ungroupClips(clipKeyList);
}

ClipKeyList TrackeditInteraction::clipsInGroup(int64_t id) const
{
    return m_interaction->clipsInGroup(id);
}

bool TrackeditInteraction::changeTracksFormat(const TrackIdList& tracksIds, trackedit::TrackFormat format)
{
    return withProgress([&, this]() {
        return withPlaybackStop(&ITrackeditInteraction::changeTracksFormat, tracksIds, format);
    });
}

bool TrackeditInteraction::changeTracksRate(const TrackIdList& tracksIds, int rate)
{
    return withPlaybackStop(&ITrackeditInteraction::changeTracksRate, tracksIds, rate);
}

bool TrackeditInteraction::swapStereoChannels(const TrackIdList& tracksIds)
{
    return withPlaybackStop(&ITrackeditInteraction::swapStereoChannels, tracksIds);
}

bool TrackeditInteraction::splitStereoTracksToLRMono(const TrackIdList& tracksIds)
{
    return withPlaybackStop(&ITrackeditInteraction::splitStereoTracksToLRMono, tracksIds);
}

bool TrackeditInteraction::splitStereoTracksToCenterMono(const TrackIdList& tracksIds)
{
    return withPlaybackStop(&ITrackeditInteraction::splitStereoTracksToCenterMono, tracksIds);
}

bool TrackeditInteraction::makeStereoTrack(const TrackId left, const TrackId right)
{
    return withPlaybackStop(&ITrackeditInteraction::makeStereoTrack, left, right);
}

bool TrackeditInteraction::resampleTracks(const TrackIdList& tracksIds, int rate)
{
    return withProgress([&, this]() {
        return withPlaybackStop(&ITrackeditInteraction::resampleTracks, tracksIds, rate);
    });
}

bool TrackeditInteraction::addLabelToSelection()
{
    return m_interaction->addLabelToSelection();
}

bool TrackeditInteraction::changeLabelTitle(const LabelKey& labelKey, const muse::String& title)
{
    return m_interaction->changeLabelTitle(labelKey, title);
}

bool TrackeditInteraction::removeLabel(const LabelKey& labelKey)
{
    return m_interaction->removeLabel(labelKey);
}

bool TrackeditInteraction::removeLabels(const LabelKeyList& labelKeys, bool moveLabels)
{
    return m_interaction->removeLabels(labelKeys, moveLabels);
}

bool TrackeditInteraction::cutLabel(const LabelKey& labelKey)
{
    return m_interaction->cutLabel(labelKey);
}

bool TrackeditInteraction::copyLabel(const LabelKey& labelKey)
{
    return m_interaction->copyLabel(labelKey);
}

bool TrackeditInteraction::moveLabels(secs_t timePositionOffset, bool completed)
{
    return m_interaction->moveLabels(timePositionOffset, completed);
}

bool TrackeditInteraction::stretchLabelLeft(const LabelKey& labelKey, secs_t newStartTime, bool completed)
{
    return m_interaction->stretchLabelLeft(labelKey, newStartTime, completed);
}

bool TrackeditInteraction::stretchLabelRight(const LabelKey& labelKey, secs_t newEndTime, bool completed)
{
    return m_interaction->stretchLabelRight(labelKey, newEndTime, completed);
}

std::optional<secs_t> TrackeditInteraction::getLeftmostLabelStartTime(const LabelKeyList& labelKeys) const
{
    return m_interaction->getLeftmostLabelStartTime(labelKeys);
}

void TrackeditInteraction::zoomInVertically(const trackedit::TrackId& trackId)
{
    m_interaction->zoomInVertically(trackId);
}

void TrackeditInteraction::zoomOutVertically(const trackedit::TrackId& trackId)
{
    m_interaction->zoomOutVertically(trackId);
}

void TrackeditInteraction::resetVerticalZoom(const trackedit::TrackId& trackId)
{
    m_interaction->resetVerticalZoom(trackId);
}

bool TrackeditInteraction::isDefaultVerticalZoom(const trackedit::TrackId& trackId) const
{
    return m_interaction->isDefaultVerticalZoom(trackId);
}

bool TrackeditInteraction::isMaxVerticalZoom(const trackedit::TrackId& trackId) const
{
    return m_interaction->isMaxVerticalZoom(trackId);
}

bool TrackeditInteraction::isMinVerticalZoom(const trackedit::TrackId& trackId) const
{
    return m_interaction->isMinVerticalZoom(trackId);
}

muse::Progress TrackeditInteraction::progress() const
{
    return m_interaction->progress();
}
}
